package com.ruoyi.backend.controller.app;

import com.ruoyi.backend.service.IUserAppService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Set;

@RestController
@RequestMapping("/app/user")
@Api(tags = "APP-用户相关接口（包括token生成）")
public class AppUserController extends BaseController {

    @Resource
    private IUserAppService userAppService;
    @Autowired
    @Qualifier("AppAuthenticationManager")
    private AuthenticationManager appAuthenticationManager;

    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysUserService userService;

    /**
     * 生成用户token
     *
     * @param loginBody
     * @return
     */
    @PostMapping("/createToken")
    @ApiOperation("生成用户token")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();

        // 用户验证
        Authentication authentication = null;
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = appAuthenticationManager.authenticate(authenticationToken);
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            } else {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        //记录登录信息
        userAppService.recordLoginInfo(loginUser.getUserId());
        // 生成token
        ajax.put(Constants.TOKEN, userAppService.createToken(loginUser));
        return ajax;
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    @RequestMapping(path = "/getCurrentUserInfo", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation("获取当前登录用户信息")
    public AjaxResult getCurrentUserInfo() {

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();

//        Integer tenantId = null;
//        if (redisCache.hasKey(CacheConstants.CURRENT_USER_TENANT_ID + user.getUserId())) {
//            tenantId = redisCache.getCacheObject(CacheConstants.CURRENT_USER_TENANT_ID + user.getUserId());
//            SysTenant sysTenant = tenantService.selectSysTenantByTenantId(tenantId);
//            user.setCurrentTenant(sysTenant);
//        } else {
//            //首先确定用户关联多少租户，如果关联一个租户，就使用关联的该租户的角色，如果关联多个租户，默认使用关联的第一个租户的角色
//            List<SysTenant> tenantList = user.getTenants();
//            if (CollectionUtil.isNotEmpty(tenantList)) {
//                user.setCurrentTenant(tenantList.get(0));
//                //将当前租户信息存入redis中
//                redisCache.setCacheObject(CacheConstants.CURRENT_USER_TENANT_ID + user.getUserId(),
//                        tenantList.get(0).getTenantId(), 1, TimeUnit.DAYS);
//            }
//        }

        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions))
        {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 根据用户id查询用户信息
     *
     * @param userId 用户id
     * @return
     */
    @GetMapping(value = "/{userId}")
    @ApiOperation("根据用户id查询用户信息")
    public AjaxResult getInfo(@PathVariable("userId") Long userId) {
        return success(userAppService.selectUserByUserId(userId));
    }

    /**
     * 新增APP端用户信息
     */
    @PostMapping("/add")
    @ApiOperation("新增用户")
    public AjaxResult add(@RequestBody SysUser user) {

        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));

        //租户ID已经传入，需要将新增用户设置为某一公司的工人
        user.setRoleIds(new Long[]{104L});

        return toAjax(userService.insertUser(user));
    }

    /**
     * 用户端app修改用户信息，只能修改用户昵称和头像
     *
     * @param appUserDTO
     * @return
     */
    @PostMapping("/updateAppUserInfo")
    @ApiOperation("修改用户信息")
    public AjaxResult updateSysUserInfo(@RequestBody SysUser appUserDTO) {
        if (appUserDTO.getUserId() == null) {
            return error("请传入用户id");
        }
        return toAjax(userAppService.updateAppUser(appUserDTO));
    }

}
